from os import listdir

import numpy as np
import operator

trainDataPath = 'trainingDigits'
testDataPath = 'testDigits'


def classify0(inX, dataSet, labels, k):
    # 计算距离
    dataSetSize = dataSet.shape[0]
    # tile（A,reqs）用于重复A  怎么重复根据reqs
    # 矩阵减法对应位置相减
    diffMat = np.tile(inX, (dataSetSize, 1)) - dataSet
    # **表示乘方
    sqDiffMat = diffMat ** 2

    sqDistances = sqDiffMat.sum(axis=1)
    distances = sqDistances ** 0.5
    sortedDistIndicies = distances.argsort()

    # 选择距离最小的k个点
    classCount = {}
    for i in range(k):
        voteIlabel = labels[sortedDistIndicies[i]]
        classCount[voteIlabel] = classCount.get(voteIlabel, 0) + 1

    # 排序 key表示按照什么参数进行排序    reverse = True 表示倒序排列
    sortedClassCount = sorted(classCount.items(), key=operator.itemgetter(1), reverse=True)
    return sortedClassCount[0][0]


def img2Vector(fileName):
    returnVect = np.zeros((1, 1024))
    fr = open(fileName)
    for i in range(32):
        lineStr = fr.readline()
        for j in range(32):
            returnVect[0, 32 * i + j] = int(lineStr[j])
    return returnVect


def handWrittingClassTest():
    hwLables = []
    # 读取文件内的文件名，返回一个列表
    trainingFileList = listdir(trainDataPath)
    m = len(trainingFileList)
    trainingMatrix = np.zeros((m, 1024))
    for i in range(m):
        fileNameStr = trainingFileList[i]
        fileStr = fileNameStr.split('.')[0]
        classNumStr = int(fileStr.split('_')[0])
        hwLables.append(classNumStr)
        trainingMatrix[i, :] = img2Vector('trainingDigits/%s' % fileNameStr)
    testFileList = listdir(testDataPath)
    errorCount = 0.0
    mTest = len(testFileList)
    for i in range(mTest):
        fileNameStr = testFileList[i]
        fileStr = fileNameStr.split('.')[0]
        classNumStr = int(fileStr.split('_')[0])
        vectorUnderTest = img2Vector('testDigits/%s' % fileNameStr)
        classifierResult = classify0(vectorUnderTest, trainingMatrix, hwLables, 3)
        print('the classifier came back with: %d , the real answer is：%d' % (
            classifierResult, classNumStr))
        if (classifierResult != classNumStr): errorCount += 1
    print('the total number of errors is :%d' % errorCount)
    print('the total errors rate is :%f' % (errorCount / float(mTest)))


handWrittingClassTest()